<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图灵一号游戏机</title>
</head>
<body>
<style>
    * {
        padding: 0px;
        margin: 0px;
    }

    .title {
        margin-top: 40px;
        font-size: 3rem;
        color: green;
    }

    .cells {
    }

    .cells .cell,.cell-target,.cell-operation, .padding {
        background-color: #323832;
        color: white;
        font-size: 5rem;
        width: 100px;
        height: 100px;
        display: inline-block;
        line-height: 100px;
     }

     .cell-target {
        background-color:green;
     }
     .usage {
        display: none;
        margin: 50px 0px 0px 0px;
        font-size: 3rem;
        text-align: center;
     }

     .code {
        display:none;
     }
     .code, .code input {
        margin-top: 30px;
        font-size: 3rem;
     }
    .code input {
         width: 40%;
     }
     .code span {
        font-size: 2rem;
     }
     .cell-title {
        margin-top: 30px;
        margin-bottom: 10px;
        font-size: 3rem;
     }
     .replay button {
        margin-top: 40px;
        font-size: 3rem;
     }
     .operation {
        margin-top: 15%;
        font-size: 2rem;
     }
     .cell-operation,.operation .padding {
        font-size: 1.5rem;
        line-height: 30px;
        height: 60px;
        width:100px;
        background-color: #a7680b;
        display: inline-block;
        vertical-align: top;
     }
     .operation .padding {
        width: 60px;
        background-color: green;
     }

</style>

<div style="text-align:center;">

    <div class="title" onclick="clickTitle();">图灵一号游戏机</div>

    <div class="usage">
        使用说明：单手指滑动、或方向键、或输入代码指令执行<br>
        🔼加1，🔽减1，◀️向左移动，▶️向右移动，最小0，最大99
    </div>

    <div class="cell-title">目标值</div>
    <div class="cells" id="targetCell">
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
        <span class="cell-target">0</span>
    </div>
    <div class="cell-title">当前值</div>
    <div class="cells">
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
        <span class="cell">0</span>
    </div>
    <div class="replay">
        <button onclick="init();">再玩一次</button>
    </div>
    <div class="code">

        <input id="code" value="++++>+++++>++++>+++++>++++++++>+++++>++++>+++++>++++>+<<<<<<<<">
        <br>
        <span class="usage">代码指令：+、-、&gt;、&lt;（后面两个是移动方向）</span>
    </div>
    <div class="operation">
        <span class="padding">　</span>
        <span class="cell-operation">上下左右<br/>滑动</span>
        <span class="padding">　</span>
    </div>
</div>

<script>

    const SELECTED_COLOR = "#a7680b";
    const COMMON_COLOR = "#323832";
    const TARGET_COLOR = "green";
    const MIN_MOVE = 10;

    // 当点击8次是显示，代码输入框
    var titleClickCount = 0;

    var currentIndex = 0;

    var isShowPassed = false;

    var startX,endX,startY,endY;

    var matchedMap = {};

    document.addEventListener('touchstart',touch, false);
    document.addEventListener('touchmove',touch, false);
    document.addEventListener('touchend',touch, false);

    function keyPress() {
        dealKeyCode();
    }

    function getPressChar() {
        return String.fromCharCode(event.which);
    }
    function changeNumber(index, number) {
       if (matchedMap[index]){
         return;
       }
       var cells = get(".cell");
       var newNumber = cells[index].innerText - (-number);
       newNumber = newNumber <= 0 ? 0 : newNumber;
       newNumber = newNumber >= 99 ? 99 : newNumber;
       cells[index].innerText = newNumber;
    }

    function dealKeyCode() {
        var keycode = event.which||event.keyCode;
        //console.log(keycode);
        switch(keycode){
        case 38: //up
          runCode("+");
          break;
        case 40: //down
          runCode("-");
          break;
        case 37: //left
          runCode("<");
          break;
        case 39: //right
          runCode(">");
          break;
        case 13: //enter
          cleanNodeCodeChar();
          var code = get("#code").value;
          for(var i=0; i<code.length; i++) {
            runCode(code.charAt(i)+"");
          }
          break;
        case 27: //esc
        case 32: //space
            break;
        }
        //console.log(currentIndex);

    }

    function moveLeft() {

        renderCell(currentIndex,COMMON_COLOR);
        currentIndex =  currentIndex<=0 ? 0 : currentIndex-1;
        renderCell(currentIndex,SELECTED_COLOR );
    }

    function moveRight() {

        renderCell(currentIndex,COMMON_COLOR);
        currentIndex =  currentIndex>=7 ? 7 : currentIndex+1;
        renderCell(currentIndex,SELECTED_COLOR );
    }

    function renderCell(index, color) {

        var cells = get(".cell");
        cells[index].style.backgroundColor = color;

    }

    function touch (event){
        var event = event || window.event;
        switch(event.type){
            case "touchstart":
                startX=event.touches[0].clientX;
                startY=event.touches[0].clientY;
                break;
            case "touchend":
                callbackTouchEnd();
                break;
            case "touchmove":
                //event.preventDefault();
                endX = event.changedTouches[0].clientX;
                endY = event.changedTouches[0].clientY;
                break;
        }
    }

    function callbackTouchEnd() {
       //console.log("startX,endX,startY,endY", startX,endX,startY,endY)

       if (Math.abs(startX-endX) > 1.5 * Math.abs(startY-endY)) {//左右滑动
            if (startX>endX+MIN_MOVE) { //向左
                runCode("<");
            } else if (startX < endX-MIN_MOVE) { //向右
               runCode(">");
            }
       } else if ( Math.abs(startX-endX) * 1.5 < Math.abs(startY-endY) ) {//上下滑动
            if (startY>endY+MIN_MOVE) { //向上
                runCode("+");
            } else if (startY < endY-MIN_MOVE) { //向下
                runCode("-");
            }
       }
    }

    function runCode(code) {

        for(var i=0; i<code.length; i++) {
            var char = code.charAt(i);
            switch(char) {
            case "+":changeNumber(currentIndex, 1);break;
            case "-":changeNumber(currentIndex, -1);break;
            case "<":moveLeft();break;
            case ">":moveRight();break;
            }
        }
        checkResult(code);
    }

    function checkResult(code) {
         var cells = get(".cell");
         var cellTargets = get(".cell-target");
         for(var i=0; i<cells.length; i++) {
            if (cells[i].innerText === cellTargets[i].innerText) {
               cells[i].style.backgroundColor = TARGET_COLOR;
               matchedMap[i] = true;
            }
         }
         if (code == ">" || code == "<") {
            renderCell(currentIndex,SELECTED_COLOR);
         }

         var matchedCount = 0;
         for(var p in matchedMap) {
            if (matchedMap[p]) {
               matchedCount ++;
            }
         }
         if (matchedCount === 8) {
            if(!isShowPassed) {
                isShowPassed = true;
                alert("恭喜通关了！");
                showOrNot(".replay", true);
            }
         }
    }

    function cleanNodeCodeChar() {

        var code = get("#code").value;
        code = code.replace(/[^+-<>]/g,"");
        get("#code").value = code;
    }

    function initTargetCellValue() {
         var cells = get(".cell-target");
         for(var i=0; i<cells.length; i++) {
            cells[i].innerText = getRandom(0,99);
         }
    }

    function initCellValue() {
         matchedMap = {};
         currentIndex = 0;
         var cells = get(".cell");
         for(var i=0; i<cells.length; i++) {
            cells[i].innerText = 0;
            cells[i].style.backgroundColor = COMMON_COLOR;
         }
    }

    function get(which) {
        if(which.charAt(0) === "#") {
            return document.getElementById(which.substring(1));
        } else if (which.charAt(0) === ".") {
            return document.getElementsByClassName(which.substring(1));
        } else {
            return document.getElementsByTagName(which);
        }
    }

    function getRandom(min, max) {
        var random = Math.round(Math.random()*10000);
        return random%max + min;
    }

    function init() {
        showOrNot(".replay", false);
        isShowPassed = false;
        initTargetCellValue();
        initCellValue();
        document.onkeyup = dealKeyCode;
        renderCell(0, SELECTED_COLOR);
    }

    function clickTitle() {
        titleClickCount++;
        if (titleClickCount>=3) {
            showOrNot(".code", true);
        }
    }

    function showOrNot(which, flag) {
        var dom = get(which);
        if (typeof(dom['length']) === 'undefined') {
            dom.style.display = "block";
        } else {
            for(var i=0;i < dom.length; i++) {
                dom[i].style.display = flag?"block":"none";
            }
        }
    }

    init();


</script>
</body>
</html>